fn main() {
	// structs are allocated on the stack
	mut p := Point {
		x: 10
		y: 20
	}
	println(p.x) // struct fields are accessed using a dot
	
	// alternative literal syntax for structs with 3 fields or fewer
	p2 := Point{10, 20}
	assert p2.x == 10
	
	// to allocate a struct on the heap and get a reference to it, use the & prefix
	p3 := &Point{10, 20}
	println(p3.x) // references have the same syntax for accessing fields
	
	fa := Foo{1}
	mut a := fa  // copy assignment
	a.x = 10
	assert fa.x == 1
	assert a.x == 10
	
	// fb := Foo{1}
	// mut b := &fb // error: `fb` is immutable, cannot have a mutable reference to it
	// b.x = 10
	
	mut fc := Foo{1}
	mut c := &fc // a reference
	c.x = 2
	assert fc.x == 2
	assert c.x == 2
	println(fc)
	println(c)
}

struct Point {
	x int
	y int
}

struct Foo {
mut:
	x int
}

// all struct fields are zeroed by default during the creation of the struct
// array and map fields are allocated
// it's also possible to define custom default values
struct Bar {
	n int        // n is 0 by default
	s string     // s is '' by default
	a []int      // a is `[]int{}` by default
	pos int = -1 // custom default value
}

struct Zoo {
	name string [required] // must be explicitly initialized
}
